/**
 *
 * 参考： https://segmentfault.com/a/1190000015467084
 * 优化：通过 X-Forwarded-For 添加了动态随机伪IP，绕过 tinypng 的上传数量限制
 *
 *  */

const fs = require("fs");
const path = require("path");
const https = require("https");
const { URL } = require("url");

// var cwd = "";

var configs = {
  cwd: "",
};

// const root = configs.cwd;
const exts = [".jpg", ".png"];
const max = 5200000; // 5MB == 5242848.754299136

const options = {
  method: "POST",
  hostname: "tinypng.com",
  path: "/web/shrink",
  headers: {
    rejectUnauthorized: false,
    "Postman-Token": Date.now(),
    "Cache-Control": "no-cache",
    "Content-Type": "application/x-www-form-urlencoded",
    "User-Agent":
      "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
  },
};

// fileList(root);

// 生成随机IP， 赋值给 X-Forwarded-For
function getRandomIP() {
  return Array.from(Array(4))
    .map(() => parseInt(Math.random() * 255))
    .join(".");
}
function outTolog() {
  console.log(...arguments);
}
function _progressCb(params) {}

// 开始压缩
function startTinypng(config, outlog, progressCb) {
  configs = Object.assign(configs, config);
  _progressCb = progressCb;
  outTolog = outlog;
  // folder, outlog, progressCb
 
    configs.cwd = config.cwd;

return fileList(configs.cwd);
 
}
// 获取文件列表
function fileList(folder) {
  return new Promise((resolve, reject) => {
    fs.readdir(folder, (err, files) => {
      if (err) return outTolog(err);
      fileFilters(files).then(fileList => {
        let index=0
        fileList.forEach((f) => {
           
        options.headers["X-Forwarded-For"] = getRandomIP();
        fileUpload(f).then(() => {
          _progressCb(fileList.length);
         
          if(index==fileList.length-1){
            resolve();
          }
          index=index+1;
          
        }); // outTolog('可以压缩：' + file);
        
      })
      });
      // files.forEach((file) => {

      //   fileFilters(path.join(folder, file)).then(f=> {
      //     options.headers["X-Forwarded-For"] = getRandomIP();
      //     fileUpload(f).then(() => {
      //       _progressCb()
      //       resolve();
      //     }); // outTolog('可以压缩：' + file);
      //   });

      // });
    });
  });
}
function fileFilters(files) {
  return new Promise((resolve, reject) => {
    let fileList = [];
    let promiseList = [];
    files.forEach((file) => {
      promiseList.push(
        fileFilter(path.join(configs.cwd, file), (_file) => {

         _file&&fileList.push(_file);
        })
      );
    });
    Promise.all(promiseList).then(() => {
      resolve(fileList);
    });
  });
}
// 过滤文件格式，返回所有jpg,png图片
function fileFilter(file, cb = false) {
  return new Promise((resolve, reject) => {
    fs.stat(file, (err, stats) => {
      if (err) return outTolog(err);
      if (
        // 必须是文件，小于5MB，后缀 jpg||png
        stats.size <= max &&
        stats.isFile() &&
        exts.includes(path.extname(file))
      ) {
        // 通过 X-Forwarded-For 头部伪造客户端IP
        // options.headers["X-Forwarded-For"] = getRandomIP();
         
        // if (stats.isDirectory()) fileList(file + '/');
        cb && cb(file);
        resolve(file);
        // fileUpload(file).then(() => {
        //   resolve();
        // }); // outTolog('可以压缩：' + file);
      } else {
        resolve(false);
      }

      // 
    });
  });
}

// 异步API,压缩图片
// {"error":"Bad request","message":"Request is invalid"}
// {"input": { "size": 887, "type": "image/png" },"output": { "size": 785, "type": "image/png", "width": 81, "height": 81, "ratio": 0.885, "url": "https://tinypng.com/web/output/7aztz90nq5p9545zch8gjzqg5ubdatd6" }}
function fileUpload(img) {
  return new Promise((resolve, reject) => {
    var req = https.request(options, function(res) {
      res.on("data", (buf) => {
        let obj = JSON.parse(buf.toString());
        if (obj.error) {
          outTolog(`[${img}]：压缩失败！报错：${obj.message}`);
        } else {
          fileUpdate(img, obj).then(() => {
            resolve();
          });
        }
      });
    });

    req.write(fs.readFileSync(img), "binary");
    req.on("error", (e) => {
      outTolog(e);
    });
    req.end();
  });
}
// 该方法被循环调用,请求图片数据
function fileUpdate(imgpath, obj) {
  return new Promise((resolve, reject) => {
    const outputDir = path.join(configs.cwd, configs.outputDir );
    imgpath = path.join(
      configs.cwd,
      configs.outputDir,
      imgpath.replace(configs.cwd, "")
    );

    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir);
    }

    let options = new URL(obj.output.url);
    let req = https.request(options, (res) => {
      let body = "";
      res.setEncoding("binary");
      res.on("data", function(data) {
        body += data;
      });

      res.on("end", function() {
        fs.writeFile(imgpath, body, "binary", (err) => {
          if (err) return outTolog(err);
          outTolog(
            `[${imgpath}] \n 压缩成功，原图[ ${Number((obj.input.size/1024).toFixed(2))}K ]，压缩后[ ${Number((obj.output.size/1024).toFixed(2))}K ]，压缩比例[ ${100-Number((obj.output.ratio*100).toFixed(2))}% ]`
          );
          resolve();
        });
      });
    });
    req.on("error", (e) => {
      outTolog(e);
    });
    req.end();
  });
}
export default {
  startTinypng: startTinypng,
};
